package com.whately.core.database.common.config;

import com.whately.core.database.db.DatabaseCfgConstant;
import com.whately.core.database.db.DynamicDataSourceContextHolder;
import lombok.extern.slf4j.Slf4j;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;

import java.util.regex.Pattern;


/**
 * 数据库操作拦截器，调用所有Dal时，
 * 会预处理,并动态设置数据库
 */
@Slf4j
public class SequenceDaoWhatelyInterceptor implements MethodInterceptor {

	/**
	 * dao中数据库 statement命名，约定为 select* insert*  update* delete.*
	 */
	private static final Pattern select = Pattern.compile("^select.*");
	private static final Pattern update = Pattern.compile("^update.*");
	private static final Pattern insert = Pattern.compile("^insert.*");
	private static final Pattern delete = Pattern.compile("^delete.*");


	@Override
	public Object invoke(MethodInvocation invocation) throws Throwable {
		log.debug("dao interceptor enter");
		//dao中的方法名称
		String old = DynamicDataSourceContextHolder.get();

		try{
			String mapperNamespace=invocation.getMethod().getDeclaringClass().getName();

			//数据源路由
			String statementId = invocation.getMethod().getName();
			String dataSource = DatabaseCfgConstant.router(mapperNamespace);
			DynamicDataSourceContextHolder.set(dataSource);

			//数据库调用开始时间
			long beginTime = System.currentTimeMillis();

			//完整的dao名称 com.whately.dal.SysUser.insert
			//String dao = mapperNamespace+"."+statementId ;

			// 校验sql是否合法
			checkDaoStatementName(mapperNamespace, statementId);

			//数据库操作返回结果
			Object result = null ;
			try{

				//执行数据库操作
				result = invocation.proceed();

			}catch(Exception e){

				if("com.whately.core.database.common.dal.mapper.RecorderOperateMapperExt".equals(mapperNamespace)&&"selectTestConnectionQuery".equals(statementId)){
					log.error("database operation exception,dao[{}],statement[{}],begintime[{}],endtime[{}].error msg [{}] ",
							mapperNamespace,
							statementId,
							beginTime,
							System.currentTimeMillis(),e.getMessage());
				}else{
					log.error("database operation exception,dao[{}],statement[{}],begintime[{}],endtime[{}]. ",
							mapperNamespace,
							statementId,
							beginTime,
							System.currentTimeMillis(),
							e);
				}

				throw e;

			}
			return result;
		}finally {
			DynamicDataSourceContextHolder.set(old);
		}

	}






	/**
	 * 检查dao方法的命名，是否符合规范，必须以select、insert、update、delete开始
	 * @return
	 *    true :
	 *    false :
	 */
	private void checkDaoStatementName(String mapperNamespace, String statementId){

		/**
		 * 命名符合规范，直接返回
		 */
		if ( select.matcher(statementId).matches() ||
				update.matcher(statementId).matches() ||
				insert.matcher(statementId).matches() ||
				delete.matcher(statementId).matches()
				) {
			return ;
		}

		/**
		 * 如果命名不符合规范，打印warn级别的日志
		 */
		log.info("statement id {}.{} is invalid, should be start with select*/insert*/update*/delete*. ", mapperNamespace,statementId);
	}





}

